//
//  EventMonitor.cpp
//  Simulation
//
//  Created by Christopher Kemsley on 2/24/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "EventMonitor.hpp"

using namespace Sim ;





EventMonitor :: EventMonitor	( Condition * inCondition , Invocation * inInvocation , Mode inMode )
:	mCondition	( inCondition )
,	mInvocation	( inInvocation )
,	mFunction	( 0 )
,	mPrevious	(  )
	{
	if ( mInvocation == 0 )
		throw Exception ( "Timer" , "Constructed with nil invocation" , __FILE__,__LINE__ ) ;
	
	if ( inCondition == 0 )
		throw Exception ( "Timer" , "Constructed with nil condition" , __FILE__,__LINE__ ) ;
	
	mInvocation -> retain () ;
	mCondition -> retain () ;
	
	mPrevious	=	(inCondition->isTrue()) & 1 ;
	
	
	if ( inMode == kModeOnRise )
		mFunction = & EventMonitor :: _fire_onRise ;
	
	else if ( inMode == kModeOnFall )
		mFunction = & EventMonitor :: _fire_onFall ;
	
	else if ( inMode == kModeOnChange )
		mFunction = & EventMonitor :: _fire_onChange ;
	
	else if ( inMode == kModeWhenOn )
		mFunction = & EventMonitor :: _fire_whenOn ;
	
	else if ( inMode == kModeWhenOff )
		mFunction = & EventMonitor :: _fire_whenOff ;
	
	performRegistration() ;
	}
EventMonitor :: ~EventMonitor ()
	{
	performUnregistration() ;
	
	mCondition -> release () ;
	mInvocation -> release () ;
	}





void	EventMonitor :: fire ()
	{
	(this->*mFunction)() ;
	}

void EventMonitor :: _fire_onRise ()
	{
	bool value = mCondition -> isTrue() & 1 ;
	if ( value != mPrevious )
		{
		mPrevious = value ;
		if ( value )
			mInvocation -> invoke() ;
		}
	}
void EventMonitor :: _fire_onFall ()
	{
	bool value = mCondition -> isTrue() & 1 ;
	if ( value != mPrevious )
		{
		mPrevious = value ;
		if ( ! value )
			mInvocation -> invoke() ;
		}
	}
void EventMonitor :: _fire_onChange ()
	{
	bool value = mCondition -> isTrue() & 1 ;
	if ( value != mPrevious )
		{
		mPrevious = value ;
		mInvocation -> invoke() ;
		}
	}

void EventMonitor :: _fire_whenOn ()
	{
	if ( mCondition -> isTrue() )
		mInvocation -> invoke() ;
	}
void EventMonitor :: _fire_whenOff ()
	{
	if ( ! mCondition -> isTrue() )
		mInvocation -> invoke() ;
	}

